package com.boarsoft.boar.deploy.component;

import com.boarsoft.boar.deploy.entity.BuildPlanItem;
import com.boarsoft.boar.deploy.plan.bean.BuildRequest;
import com.boarsoft.flow.core.bean.ProcessHandler;
import com.jcraft.jsch.*;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class UploadZipPH implements ProcessHandler {

	private String remoteAddress;

	private String remoteUser;

	private String remotePasswd;

	private String remotePath;

	@Override
	public Object process(String entry, Object data, Throwable throwable) throws Throwable {
		BuildPlanItem bp=((BuildRequest)data).getCurPlanItem();
		//压缩ZIP包
		File directoryToZip = new File(bp.getPackPath());
		String zipName=bp.getPackPath()+".zip";
		File outputZipFile = new File(zipName);
		try {
			FileOutputStream fos = new FileOutputStream(outputZipFile);
			ZipOutputStream zos = new ZipOutputStream(fos);
			zipFile(directoryToZip, directoryToZip.getName(), zos);
			zos.close();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		//上传ZIP包
		JSch jsch = new JSch();
		Session session = null;
		ChannelSftp sftpChannel = null;

		try {
			session = jsch.getSession(remoteUser, remoteAddress, 22);
			session.setPassword(remotePasswd);

			// Disable host key checking for demonstration purposes
			session.setConfig("StrictHostKeyChecking", "no");

			session.connect();

			Channel channel = session.openChannel("sftp");
			channel.connect();

			sftpChannel = (ChannelSftp) channel;
			sftpChannel.cd(remotePath);
			sftpChannel.put(zipName, remotePath,new MyProgressMonitor());

			//解压上传的zip包
			ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
			channelExec.setCommand("cd "+remotePath+";rm -rf "+outputZipFile.getName().replace(".zip","")+";unzip "+outputZipFile.getName());
			channelExec.setErrStream(System.err);
			channelExec.getInputStream();

			channelExec.connect();

			// Read the output from the command
			InputStream in = channelExec.getInputStream();
			byte[] tmp = new byte[1024];
			while (true) {
				while (in.available() > 0) {
					int i = in.read(tmp, 0, 1024);
					if (i < 0) break;
					System.out.print(new String(tmp, 0, i));
				}
				if (channelExec.isClosed()) {
					break;
				}
			}

			channelExec.disconnect();
			session.disconnect();

		} catch (JSchException | SftpException e) {
			e.printStackTrace();
		} finally {
			if (sftpChannel != null) {
				sftpChannel.exit();
			}
			if (session != null) {
				session.disconnect();
			}
		}
		bp.setRemotePath(remotePath+outputZipFile.getName().replace(".zip",""));
		return data;
	}

	public static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
		if (fileToZip.isHidden()) {
			return;
		}
		if (fileToZip.isDirectory()) {
			if (fileName.endsWith("/")) {
				zipOut.putNextEntry(new ZipEntry(fileName));
				zipOut.closeEntry();
			} else {
				zipOut.putNextEntry(new ZipEntry(fileName + "/"));
				zipOut.closeEntry();
			}
			File[] children = fileToZip.listFiles();
			for (File childFile : children) {
				zipFile(childFile, fileName + "/" + childFile.getName(), zipOut);
			}
			return;
		}
		FileInputStream fis = new FileInputStream(fileToZip);
		ZipEntry zipEntry = new ZipEntry(fileName);
		zipOut.putNextEntry(zipEntry);
		byte[] bytes = new byte[1024];
		int length;
		while ((length = fis.read(bytes)) >= 0) {
			zipOut.write(bytes, 0, length);
		}
		fis.close();
	}


	public String getRemoteAddress() {
		return remoteAddress;
	}

	public void setRemoteAddress(String remoteAddress) {
		this.remoteAddress = remoteAddress;
	}

	public String getRemotePath() {
		return remotePath;
	}

	public void setRemotePath(String remotePath) {
		this.remotePath = remotePath;
	}

	public String getRemoteUser() {
		return remoteUser;
	}

	public void setRemoteUser(String remoteUser) {
		this.remoteUser = remoteUser;
	}

	public String getRemotePasswd() {
		return remotePasswd;
	}

	public void setRemotePasswd(String remotePasswd) {
		this.remotePasswd = remotePasswd;
	}

	public static class MyProgressMonitor implements SftpProgressMonitor {
		private long transfered;

		private double total;

		@Override
		public void init(int op, String src, String dest, long max) {
			total=max;
			System.out.println("STARTED: " + src + " to " + dest + " total: " + max + " bytes");
		}

		@Override
		public boolean count(long count) {
			transfered += count;
			System.out.println("Uploaded: "+  String.format("%.2f", transfered/total*100) + "%");
			return true;
		}

		@Override
		public void end() {
			System.out.println("Transfer completed.");
		}
	}
}
